iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
JavaScript

不要再說你不會後端!30 天 Node.js 降維打擊指南 系列 第 21 篇

Day 21:JWT (JSON Web Token) 身分驗證機制的魔法

  • 分享至 

  • xImage
  •  

正式進入第四階段:「安全與驗證」!

在前面的課程中,我們的 API 就像是一個完全不設防的公園,任何人都可以呼叫 GET /api/users 或 DELETE /api/todos/1。但在真實世界中,刪除任務或修改個人資料,必須是「登入後的本人」才能操作。

因為 HTTP 協定天生是「無狀態 (Stateless)」的,伺服器是個金魚腦,上一秒你才剛登入,下一秒你發送修改密碼的請求時,它就忘記你是誰了。為了證明「我真的是剛剛那個登入成功的人」,我們需要一張 VIP 通行證,而現代 API 最主流的通行證就是 JWT (JSON Web Token)。


1. 什麼是 JWT?

JWT 是一串看起來像亂碼的字串(通常長這樣:xxxxx.yyyyy.zzzzz),它由三個部分組成,中間用句號 . 隔開:

  1. Header (標頭):紀錄這張通行證是用什麼演算法加密的。
  2. Payload (內容):紀錄你要夾帶的非敏感資訊,例如使用者的 ID (userId: 99)、權限等級 (role: "admin") 以及通行證的過期時間。
  3. Signature (簽章):這是 JWT 的防偽核心。伺服器會用一把「只有伺服器自己知道的秘密鑰匙 (Secret Key)」將前面兩個部分進行數位簽章。如果駭客偷偷把 Payload 裡的 userId: 99 改成 userId: 1 (試圖偽裝成老闆),伺服器一驗證簽章就會發現被篡改,直接拒絕請求。

2. 實作練習:核發與驗證通行證

我們將使用業界最通用的 jsonwebtoken 套件。
請在專案中安裝:
npm install jsonwebtoken

在資料夾下新增一個 auth-demo.js,輸入以下程式碼:

import jwt from 'jsonwebtoken';

// 這是伺服器的最高機密,絕對不能外流!(實務上會放在 .env 檔案裡,明天會教)
const SECRET_KEY = "my_super_secret_key_dont_tell_anyone";

// 模擬:1. 登入成功,核發 JWT 通行證
const loginAndGenerateToken = () => {
    // 假設使用者帳密輸入正確,我們從資料庫查到他的 ID 是 101
    const userData = {
        userId: 101,
        username: "Bibo",
        role: "user"
    };

    // 使用 jwt.sign(內容, 密鑰, 設定選項) 來產生 Token
    const token = jwt.sign(
        userData, 
        SECRET_KEY, 
        { expiresIn: '1h' } // 設定 1 小時後過期
    );
    
    console.log(" 成功核發 Token:\n", token, "\n");
    return token;
};

// 模擬:2. 使用者帶著 Token 來請求受保護的 API
const verifyUserToken = (clientToken) => {
    try {
        // jwt.verify() 會自動檢查:1. 簽章是否正確 2. 是否過期
        const decodedPayload = jwt.verify(clientToken, SECRET_KEY);
        
        console.log(" 驗證成功!歡迎回來,使用者:", decodedPayload.username);
        console.log("你的完整 Payload:", decodedPayload);
        
    } catch (error) {
        // 常見錯誤包含:JsonWebTokenError (簽章錯誤/被篡改)、TokenExpiredError (已過期)
        console.error(" 驗證失敗,請重新登入!錯誤原因:", error.message);
    }
};

// --- 執行測試 ---
console.log("--- 模擬登入流程 ---");
const myToken = loginAndGenerateToken();

console.log("\n--- 模擬拿著正確的 Token 去請求 API ---");
verifyUserToken(myToken);

console.log("\n--- 模擬駭客拿著被篡改的 Token 去請求 API ---");
const fakeToken = myToken + "hack"; // 故意破壞 Token 結構
verifyUserToken(fakeToken);

3. JWT 的致命安全守則

請永遠記住一件事:JWT 的 Payload 只是經過 Base64 編碼,並沒有加密!
任何人拿到你的 Token,都可以去 jwt.io 網站把 Payload 的內容完全解碼看光光。

絕對、絕對、絕對不可以把使用者的「密碼」、「信用卡號」等敏感資訊塞進 Payload 裡面!Payload 只適合放 id 或 role 這種用來識別身分的不敏感資料。


上一篇
# Day 20:MongoDB 聚合管道 (Aggregation Pipeline) 的數據煉金術
下一篇
Day 22:伺服器的終極防禦(密碼加密 Bcrypt 與環境變數 dotenv)
系列文
不要再說你不會後端!30 天 Node.js 降維打擊指南 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言